package com.shop.shopserver.config;

import com.shop.shopcommon.properties.WebSecurityProperties;
import com.shop.shopserver.handler.CustomLogoutSuccessHandler;
import com.shop.shopserver.filter.CustomAuthenticationFilter;
import com.shop.shopserver.provider.CustomUsernamePasswordAuthenticationProvider;
import com.shop.shopserver.provider.PhoneVerificationAuthenticationProvider;
import com.shop.shopserver.service.PasswordUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.PostConstruct;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private final CustomUsernamePasswordAuthenticationProvider customUsernamePasswordAuthenticationProvider;

    private final PhoneVerificationAuthenticationProvider phoneVerificationAuthenticationProvider;

    @Autowired
    private WebSecurityProperties webSecurityProperties;

    public SecurityConfiguration(PhoneVerificationAuthenticationProvider phoneVerificationAuthenticationProvider,
                                 CustomUsernamePasswordAuthenticationProvider customUsernamePasswordAuthenticationProvider) {
        // Provider需要的密码解码器和自定义的用户详情服务由构造函数注入
        this.phoneVerificationAuthenticationProvider = phoneVerificationAuthenticationProvider;
        this.customUsernamePasswordAuthenticationProvider = customUsernamePasswordAuthenticationProvider;
    }


    /**
     * 注册手机验证码认证管理器
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // AuthenticationProvider可以在这里添加
        // 注册手机号和验证码的认证提供者
        auth.authenticationProvider(phoneVerificationAuthenticationProvider);
        auth.authenticationProvider(customUsernamePasswordAuthenticationProvider);
    }

    /**
     * 配置 HttpSecurity
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()  // 根据需求决定是否禁用 CSRF
                .authorizeRequests()
                //.antMatchers("/login", "/doc.html","/webjars/**", "/swagger-ui/**", "/v2/api-docs", "/swagger-resources/**").permitAll() // 允许所有用户访问自定义登录路径
                //.antMatchers("/login","/user/getNoteCode").permitAll()// 开发模式开发所有接口
                .antMatchers("/**").permitAll()
                .antMatchers("/user/getC").authenticated() // 只有认证用户能访问此受保护资源
                .anyRequest().denyAll() // 其他未明确配置的路径默认拒绝访问
                .and()
                .addFilterBefore(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) // 将自定义过滤器放在 UsernamePasswordAuthenticationFilter 之前
                .rememberMe()
                .tokenValiditySeconds(webSecurityProperties.getTokenValiditySeconds()) // 设置记住我功能的有效期为 1 天（86400 秒）
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
                .maximumSessions(webSecurityProperties.getMaximumSessions()) // 同一用户只能有一个活跃的会话
                .maxSessionsPreventsLogin(true) // 阻止新的登录请求
                .and()
                .and()
                .logout()// 配置退出登录相关设置
                // 自定义退出登录的 URL，默认是 /logout
                .logoutUrl(webSecurityProperties.getLogoutUrl())
                // 退出登录成功处理逻辑
                .logoutSuccessHandler(new CustomLogoutSuccessHandler())
                .invalidateHttpSession(true) // 使 HttpSession 失效
                .clearAuthentication(true) // 清除认证信息
                .deleteCookies("JSESSIONID", "remember-me", webSecurityProperties.getLoginCookieName()) // 删除相关 Cookie，这里假设“记住我”功能的 Cookie 名为 remember-me
                .and()
                .httpBasic();
    }

    /**
     * 创建自定义的认证过滤器
     */
    @Bean
    public CustomAuthenticationFilter customAuthenticationFilter() throws Exception {
        // 创建自定义的认证过滤器,拦截/login路径
        return new CustomAuthenticationFilter(webSecurityProperties.getLoginProcessingUrl(), authenticationManager());
    }

    /**
     * 创建自定义的退出登录成功处理逻辑
     */
    @Bean
    public CustomLogoutSuccessHandler customLogoutSuccessHandler() {
        return new CustomLogoutSuccessHandler();
    }

    /**
     * 创建自定义的认证管理器，用于在自定义过滤器是将认证请求委托给它
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}
